﻿// (c)2010 David Schwarz (david.schwarz@live.com)
// This file is licensed under GNU GPL v2 license, see more at http://www.gnu.org/licenses/gpl-2.0.html
namespace vKapse.DDTool.Core
{

	#region Using

	using System;
	using System.Collections.Generic;
	using System.Drawing;
	using System.Windows.Forms;
	using Z2.Editor;

	#endregion

	/// <summary>
	/// Abstraktní třída pro Spouštěč
	/// </summary>
	public abstract class TriggerBase
	{

		#region Const

		private const string DEFAULT_TEXT = "Trigger";

		#endregion

		#region Members

		private AddTriggerMode m_mode;
		private string m_text;
		private string m_toolTip;
		private Image m_image;
		private bool m_isEnabled;
		private bool m_isVisible;
		private bool m_isComboBox;
		private bool m_isChekcBox;
		private bool m_isChecked;
		private bool m_toToolBar;
		private Keys m_shortcut;
		private List<string> m_list;

		private Dictionary<object, TriggerAssociationBase> m_associations; // Asociace této spouště

		private static List<TriggerAssociationBase> _all; // Statický seznam asociací
		private static List<TriggerBase> _triggers; // Seznam všech triggerů v aplikaci

		#endregion Members

		#region Constructor

		/// <summary>
		/// Statický konstruktor
		/// </summary>
		static TriggerBase()
		{
			_all = new List<TriggerAssociationBase>();
			_all.Add(new ToolBarItemAssociation());
			_all.Add(new ToolStripMenuItemAssociation());

			_triggers = new List<TriggerBase>();
		}


		/// <summary>
		/// Konstruktor
		/// </summary>
		protected TriggerBase()
		{
			_triggers.Add(this);
			this.m_list = new List<string>();
			this.m_image = null;
			this.m_text = TriggerBase.DEFAULT_TEXT;
			this.m_toolTip = string.Empty;
			this.m_isEnabled =
				this.m_isVisible = true;
			this.m_associations = new Dictionary<object, TriggerAssociationBase>();
			this.m_toToolBar = true;
			this.m_mode = AddTriggerMode.Both;
		}

		#endregion Constructor

		#region Methods

		/// <summary>
		/// Metoda refreshne všechny triggery
		/// </summary>
		public static void RefreshConditions()
		{
			_triggers.ForEach(delegate(TriggerBase trigger)
			{
				trigger.Enabled = trigger.Conditions();
			});
		}

		/// <summary>
		/// Zjistí, zda mají být objekty povoleny či kazázány
		/// </summary>
		/// <returns></returns>
		protected virtual bool Conditions()
		{
			return true;
		}

		/// <summary>
		/// Vrací seznam asociovaných objektů
		/// </summary>
		/// <returns><see cref="List"/></returns>
		protected List<object> GetAssociated()
		{
			List<object> obj = new List<object>();
			foreach (object item in this.m_associations.Keys)
			{
				obj.Add(item);
			}
			return obj;
		}

		/// <summary>
		/// Spoustí spouštěč
		/// </summary>
		public void Run()
		{
			if (this.Triggered == null || !this.Enabled)
			{
				return;
			}
			this.Triggered(this, EventArgs.Empty);
		}

		/// <summary>
		/// Odstraní asociaci spouštěče s objektem
		/// </summary>
		/// <param name="obj">Objekt</param>
		public void Disassociate(object obj)
		{
			if (!this.m_associations.ContainsKey(obj))
			{
				return;
			}
			this.m_associations[obj].Unregister(obj);
			this.m_associations.Remove(obj);
		}

		/// <summary>
		/// Asociuje spouštěč s objektem
		/// </summary>
		/// <param name="obj">Objekt</param>
		public void Associate(object obj)
		{
			// Pokud je objekt s tímto trigerem asociován
			if (this.m_associations.ContainsKey(obj))
			{
				return;
			}
			Type type = obj.GetType(); // Získáme typ objektu
			TriggerAssociationBase association = _all.Find(delegate(TriggerAssociationBase match)
				{
					return (match.Type == type || match.Type == type.BaseType);
				});
			// Nalezeno?
			if (association != null)
			{
				// Přidáme ho do asociací
				this.m_associations.Add(obj, association);
				association.Register(this, obj); // Zaregistrujeme
				association.ApplyChanges(this, obj);
			}
		}

		/// <summary>
		/// Volá se po změně properties
		/// </summary>
		protected void PropertyChanged()
		{
			foreach(object obj in this.m_associations.Keys)
			{
				TriggerAssociationBase association = this.m_associations[obj];
				association.ApplyChanges(this, obj);
			}
		}

		#endregion Methods

		#region Properties

		internal object[] Associations
		{
			get
			{
				return this.GetAssociated().ToArray();
			}
		}

		public AddTriggerMode Mode
		{
			get
			{
				return this.m_mode;
			}
			set
			{
				this.m_mode = value;
			}
		}

		/// <summary>
		/// Teď momentálně nevim, kde se tohle používá :))
		/// </summary>
		public bool ToToolBar
		{
			get
			{
				return this.m_toToolBar;
			}
			protected set
			{
				this.m_toToolBar = value;
			}
		}

		/// <summary>
		/// Obsahuje true, pokud je zaškrtnutý
		/// </summary>
		public bool IsChecked
		{
			get
			{
				return this.m_isChecked;
			}
			set
			{
				this.m_isChecked = value;
				this.PropertyChanged();
			}
		}

		/// <summary>
		/// Indikuje, zda se jedná o checkbox
		/// </summary>
		public bool IsCheckBox
		{
			get
			{
				return this.m_isChekcBox;
			}
			set
			{
				this.m_isChekcBox = value;
			}
		}

		/// <summary>
		/// Obsahuje položky rozbolaovacího menu
		/// </summary>
		public List<string> List
		{
			get
			{
				return this.m_list;
			}
			set
			{
				this.m_list = value;
			}
		}

		/// <summary>
		/// Indikuje, zda se jedná o rozbalovací menu
		/// </summary>
		public bool IsComboBox
		{
			get
			{
				return this.m_isComboBox;
			}
			set
			{
				this.m_isComboBox = value;
			}
		}

		/// <summary>
		/// Nastaví nebo vrátí zkratku
		/// </summary>
		public Keys Shortcut
		{
			get
			{
				return this.m_shortcut;
			}
			set
			{
				this.m_shortcut = value;
			}
		}

		/// <summary>
		/// Zobrazí či skryje spouštěč
		/// </summary>
		public bool Visible
		{
			get
			{
				return this.m_isVisible;
			}
			set
			{
				this.m_isVisible = value;
				this.PropertyChanged();
			}
		}

		/// <summary>
		/// Povolí či zakáže spouštěč
		/// </summary>
		public bool Enabled
		{
			get
			{
				return this.m_isEnabled;
			}
			set
			{
				this.m_isEnabled = value;
				this.PropertyChanged();
			}
		}

		/// <summary>
		/// Nastaví nebo vrátí obrázek spouštěče
		/// </summary>
		public Image Image
		{
			get
			{
				return this.m_image;
			}
			set
			{
				this.m_image = value;
				this.PropertyChanged();
			}
		}

		/// <summary>
		/// Nastaví nebo vrátí Tool Tip Text
		/// </summary>
		public string ToolTipText
		{
			get
			{
				return this.m_toolTip;
			}
			set
			{
				this.m_toolTip = value;
				this.PropertyChanged();
			}
		}

		/// <summary>
		/// Nastaví nebo vrátí text spouštěče
		/// </summary>
		public string Text
		{
			get
			{
				return this.m_text;
			}
			set
			{
				this.m_text = value;
				this.PropertyChanged();
			}
		}

		#endregion Properties

		#region Events

		/// <summary>
		/// Událost, která nastane po spuštění spouštěče
		/// </summary>
		public event EventHandler Triggered;

		#endregion Events

	}
}
